﻿// <copyright file="Ribbon1.cs" company="Microsoft Corporation">
// Copyright (c) 2009 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2010-06-30</date>
// <summary>Ribbon1 class definition</summary>

namespace WordFlowDocumentCreator
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using Microsoft.Office.Core;
    using stdole;
    using Synergist.WordToXamlLibrary;
    using Office = Microsoft.Office.Core;

    /// <summary>
    /// RibbonX code behind
    /// </summary>
    /// <remarks>See this article for ribbon callback method signatures: http://msdn.microsoft.com/EN-US/library/A16C7DF5-93F3-4920-BAA8-7B7290794C15.aspx </remarks>
    [ComVisible(true)]
    public class Ribbon1 : Office.IRibbonExtensibility
    {
        #region Fields
        /// <summary>
        /// The ribbon UI
        /// </summary>
        private Office.IRibbonUI ribbon;

        /// <summary>
        /// The FlowDocument options
        /// </summary>
        private FlowDocumentOptions options;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the Ribbon1 class
        /// </summary>
        public Ribbon1()
        {
            this.options = new FlowDocumentOptions();

            this.InitializeOptions();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Save the options to the settings file
        /// </summary>
        public void SaveOptions()
        {
            Properties.Settings.Default.AutoColumnWidth = this.options.AutoColumnWidth;
            Properties.Settings.Default.AutoPagePadding = this.options.AutoPagePadding;
            Properties.Settings.Default.ColumnWidth = this.options.ColumnWidth;
            Properties.Settings.Default.ColumnWidthUnits = this.options.ColumnWidthUnits;
            Properties.Settings.Default.DropShadowNoise = this.options.DropShadowNoise;
            Properties.Settings.Default.DropShadowSoftness = this.options.DropShadowSoftness;
            Properties.Settings.Default.IsColumnWidthFlexible = this.options.IsColumnWidthFlexible;
            Properties.Settings.Default.IsHyphenationEnabled = this.options.IsHyphenationEnabled;
            Properties.Settings.Default.IsOptimalParagraphEnabled = this.options.IsOptimalParagraphEnabled;
            Properties.Settings.Default.PagePadding = this.options.PagePadding;
            Properties.Settings.Default.PagePaddingUnits = this.options.PagePaddingUnits;
            Properties.Settings.Default.XamlType = this.options.XamlType;

            Properties.Settings.Default.Save();
        }
        #endregion

        #region Ribbon Callbacks

        /// <summary>
        /// Load the ribbon
        /// </summary>
        /// <param name="ribbonUI">the ribbon UI</param>
        public void RibbonLoad(Office.IRibbonUI ribbonUI)
        {
            this.ribbon = ribbonUI;
        }

        /// <summary>
        /// Load an image
        /// </summary>
        /// <param name="imageId">the image ID</param>
        /// <returns>the Picture Dispatch interface</returns>
        public IPictureDisp LoadImage(string imageId)
        {
            switch (imageId)
            {
                case "Silverlight":
                    return AxHostConverter.ImageToPictureDisp(global::WordFlowDocumentCreator.Properties.Resources.silverlightLogo);

                case "WPF":
                    return AxHostConverter.ImageToPictureDisp(Properties.Resources.wpf);

                case "Preview":
                    return AxHostConverter.ImageToPictureDisp(Properties.Resources.SaveAsFlowDocumentImage);

                case "Xaml":
                    return AxHostConverter.ImageToPictureDisp(Properties.Resources.xaml);

                default:
                    break;
            }

            return null;
        }

        /// <summary>
        /// Get the page padding
        /// </summary>
        /// <param name="control">the Page padding edit control</param>
        /// <returns>the page padding text</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "method signature must be exact.")]
        public string GetPagePadding(IRibbonControl control)
        {
            return this.options.PagePadding.ToString(CultureInfo.CurrentCulture);
        }

        /// <summary>
        /// Gets a value indicating whether a certain XAML type is pressed
        /// </summary>
        /// <param name="control">One of the XAML type controls</param>
        /// <returns>true if the XAML option is selected</returns>
        public bool GetXamlTypePressed(IRibbonControl control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "WPFButton":
                    return this.options.XamlType == XamlType.WPF;

                case "SilverlightRichTextBoxButton":
                    return this.options.XamlType == XamlType.SilverlightRichTextBox;

                case "SilverlightStackPanelButton":
                    return this.options.XamlType == XamlType.SilverlightStackPanel;
            }

            throw new InvalidOperationException("Invalid control Id for Xaml Type button.");
        }

        /// <summary>
        /// Handle when the user presses a XAML Type Button
        /// </summary>
        /// <param name="control">the button</param>
        /// <param name="pressed">whether the button is pressed or not</param>
        public void XamlTypePressed(IRibbonControl control, bool pressed)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            if (pressed)
            {
                switch (control.Id)
                {
                    case "WPFButton":
                        this.options.XamlType = XamlType.WPF;
                        this.ribbon.InvalidateControl("SilverlightRichTextBoxButton");
                        this.ribbon.InvalidateControl("SilverlightStackPanelButton");
                        break;

                    case "SilverlightRichTextBoxButton":
                        this.options.XamlType = XamlType.SilverlightRichTextBox;
                        this.ribbon.InvalidateControl("WPFButton");
                        this.ribbon.InvalidateControl("SilverlightStackPanelButton");
                        break;

                    case "SilverlightStackPanelButton":
                        this.options.XamlType = XamlType.SilverlightStackPanel;
                        this.ribbon.InvalidateControl("WPFButton");
                        this.ribbon.InvalidateControl("SilverlightRichTextBoxButton");
                        break;

                    default:
                        throw new InvalidOperationException("Invalid control Id for Xaml Type button.");
                }
            }

            this.ribbon.InvalidateControl("OptionsGroup");
            this.ribbon.InvalidateControl("ColumnWidthGroup");
        }

        /// <summary>
        /// Get the selected page padding units
        /// </summary>
        /// <param name="control">the page padding units dropdown control</param>
        /// <returns>the ID of the selected Page Padding value</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "Signature for RibbonX cannot change.")]
        public string GetSelectedPagePaddingUnits(IRibbonControl control)
        {
            switch (this.options.PagePaddingUnits)
            {
                case PagePaddingUnits.Inches:
                    return "PagePaddingInches";

                case PagePaddingUnits.Pixels:
                    return "PagePaddingPixels";
            }

            throw new InvalidOperationException("Invalid Page padding units.");
        }

        /// <summary>
        /// Gets the selected column widht units
        /// </summary>
        /// <param name="control">the column width units control</param>
        /// <returns>the units id</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "Signature for RibbonX cannot change.")]
        public string GetSelectedColumnWidthUnits(IRibbonControl control)
        {
            switch (this.options.ColumnWidthUnits)
            {
                case "px":
                    return "ColumnWidthPixels";

                case "in":
                    return "ColumnWidthInches";

                case "cm":
                    return "ColumnWidthCentimeters";

                case "pt":
                    return "ColumnWidthPoints";
            }

            throw new InvalidOperationException("Invalid Column Width units.");
        }

        /// <summary>
        /// Gets a value indicating whether the button is pressed
        /// </summary>
        /// <param name="control">the ribbon control checkbox</param>
        /// <returns>true if pressed</returns>
        public bool GetPressed(IRibbonControl control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "AutoPagePadding":
                    return this.options.AutoPagePadding;

                case "AutoHyphenation":
                    return this.options.IsHyphenationEnabled;

                case "OptimalParagraph":
                    return this.options.IsOptimalParagraphEnabled;

                case "AutomaticWidthColumns":
                    return this.options.AutoColumnWidth;

                case "FlexibleWidthColumns":
                    return this.options.IsColumnWidthFlexible;

                default:
                    throw new InvalidOperationException("Invalid Control Id.");
            }
        }

        /// <summary>
        /// Gets a value indicating whether the control should be visible
        /// </summary>
        /// <param name="control">the ribbon control</param>
        /// <returns>true if the control should be visible</returns>
        public bool GetVisible(IRibbonControl control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "OptionsGroup":
                    return this.options.XamlType == XamlType.WPF;

                case "ColumnWidthGroup":
                    return this.options.XamlType == XamlType.WPF;

                default:
                    throw new InvalidOperationException("Invalid Control Id.");
            }
        }

        /// <summary>
        /// Gets a value indicating whether the control should be enabled
        /// </summary>
        /// <param name="control">the ribbon control</param>
        /// <returns>true if the control should be enabled</returns>
        public bool GetEnabled(IRibbonControl control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "PagePadding":
                    return !this.options.AutoPagePadding;

                case "PagePaddingUnits":
                    return !this.options.AutoPagePadding;

                case "ColumnWidth":
                    return !this.options.AutoColumnWidth;

                case "ColumnWidthUnits":
                    return !this.options.AutoColumnWidth;

                default:
                    throw new InvalidOperationException("Invalid control Id.");
            }
        }

        /// <summary>
        /// Checkbox OnAction handler
        /// </summary>
        /// <param name="control">the ribbon checkbox control</param>
        /// <param name="pressed">true if pressed</param>
        public void OnAction(IRibbonControl control, bool pressed)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "AutoHyphenation":
                    this.options.IsHyphenationEnabled = pressed;
                    break;

                case "AutoPagePadding":
                    this.options.AutoPagePadding = pressed;
                    this.ribbon.InvalidateControl("PagePadding");
                    this.ribbon.InvalidateControl("PagePaddingUnits");
                    break;

                case "OptimalParagraph":
                    this.options.IsOptimalParagraphEnabled = pressed;
                    break;

                case "AutomaticWidthColumns":
                    this.options.AutoColumnWidth = pressed;
                    this.ribbon.InvalidateControl("ColumnWidth");
                    this.ribbon.InvalidateControl("ColumnWidthUnits");
                    break;

                case "FlexibleWidthColumns":
                    this.options.IsColumnWidthFlexible = pressed;
                    break;

                default:
                    throw new InvalidOperationException("Invalid control Id.");
            }
        }

        /// <summary>
        /// Handle when the page padding units change
        /// </summary>
        /// <param name="control">the drop down ribbon control</param>
        /// <param name="selectedId">the selected id</param>
        /// <param name="selectedIndex">the selected index</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "Signature for RibbonX cannot change."), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "selectedIndex", Justification = "Signature for RibbonX cannot change.")]
        public void OnPagePaddingUnitsChanged(IRibbonControl control, string selectedId, int selectedIndex)
        {
            switch (selectedId)
            {
                case "PagePaddingPixels":
                    this.options.PagePaddingUnits = PagePaddingUnits.Pixels;
                    break;

                case "PagePaddingInches":
                    this.options.PagePaddingUnits = PagePaddingUnits.Inches;
                    break;

                default:
                    throw new InvalidOperationException("Invalid Page padding units selected.");
            }
        }

        /// <summary>
        /// Handle when the user selects a different column width unit
        /// </summary>
        /// <param name="control">the column width drop down control</param>
        /// <param name="selectedId">the selected id</param>
        /// <param name="selectedIndex">the selected index</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "Signature for RibbonX cannot change."), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "selectedIndex", Justification = "Signature for RibbonX cannot change.")]
        public void OnColumnWidthUnitsChanged(IRibbonControl control, string selectedId, int selectedIndex)
        {
            switch (selectedId)
            {
                case "ColumnWidthPixels":
                    this.options.ColumnWidthUnits = "px";
                    break;

                case "ColumnWidthInches":
                    this.options.ColumnWidthUnits = "in";
                    break;

                case "ColumnWidthCentimeters":
                    this.options.ColumnWidthUnits = "cm";
                    break;

                case "ColumnWidthPoints":
                    this.options.ColumnWidthUnits = "pt";
                    break;

                default:
                    throw new InvalidOperationException("Invalid column width units selected.");
            }
        }

        /// <summary>
        /// TextBox change event handler
        /// </summary>
        /// <param name="control">the ribbon control text box</param>
        /// <param name="text">the new text</param>
        public void OnChange(IRibbonControl control, string text)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "ColumnWidth":
                    double columnWidth = 0;

                    if (double.TryParse(text, out columnWidth))
                    {
                        this.options.ColumnWidth = columnWidth;
                    }
                    else
                    {
                        this.ribbon.InvalidateControl("ColumnWidth");
                    }

                    break;

                case "DropShadowSoftness":
                    double dropShadowSoftness = 0;

                    if (double.TryParse(text, out dropShadowSoftness) && dropShadowSoftness >= 0 && dropShadowSoftness <= 100)
                    {
                        this.options.DropShadowSoftness = dropShadowSoftness;
                    }
                    else
                    {
                        this.ribbon.InvalidateControl("DropShadowSoftness");
                    }

                    break;

                case "DropShadowNoise":
                    double dropShadowNoise = 0;

                    if (double.TryParse(text, out dropShadowNoise) && dropShadowNoise >= 0 && dropShadowNoise <= 100)
                    {
                        this.options.DropShadowNoise = dropShadowNoise;
                    }
                    else
                    {
                        this.ribbon.InvalidateControl("DropShadowNoise");
                    }

                    break;

                case "PagePadding":
                    double pagePadding = 0;

                    if (double.TryParse(text, out pagePadding) && pagePadding >= 0)
                    {
                        this.options.PagePadding = pagePadding;
                    }
                    else
                    {
                        this.ribbon.InvalidateControl("PagePadding");
                    }

                    break;

                default:
                    throw new InvalidOperationException("Invalid control Id.");
            }
        }

        /// <summary>
        /// Get the text for a ribbon edit box
        /// </summary>
        /// <param name="control">the control</param>
        /// <returns>the control text</returns>
        public string GetText(IRibbonControl control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            switch (control.Id)
            {
                case "ColumnWidth":
                    return this.options.ColumnWidth.ToString(CultureInfo.CurrentCulture);

                case "DropShadowSoftness":
                    return this.options.DropShadowSoftness.ToString(CultureInfo.CurrentCulture);

                case "DropShadowNoise":
                    return this.options.DropShadowNoise.ToString(CultureInfo.CurrentCulture);

                default:
                    throw new InvalidOperationException("Invalid control Id");
            }
        }

        /// <summary>
        /// Show the XAML Preview
        /// </summary>
        /// <param name="control">the preview ribbon control button</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "Signature for RibbonX cannot change.")]
        public void PreviewClick(IRibbonControl control)
        {
            Cursor.Current = Cursors.WaitCursor;

            string wordOpenXML = Globals.ThisAddIn.Application.ActiveDocument.WordOpenXML;

            FlowDocumentCreator creator = new FlowDocumentCreator(this.options);

            creator.ShowFlowDocument(wordOpenXML);
        }

        /// <summary>
        /// Show the about page
        /// </summary>
        /// <param name="control">the ribbon control button</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "control", Justification = "Signature for RibbonX cannot change.")]
        public void AboutClick(IRibbonControl control)
        {
            FlowDocumentCreator.ShowXaml(Properties.Resources.about);
        }

        /// <summary>
        /// Save the current word document as XAML
        /// </summary>
        /// <param name="control">the ribbon control button</param>
        public void SaveAsXaml(IRibbonControl control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            XamlType previousType = this.options.XamlType;

            switch (control.Id)
            {
                case "FileSaveAsFlowDocument":
                    this.options.XamlType = XamlType.WPF;
                    break;

                case "FileSaveAsSilverlightStackPanel":
                    this.options.XamlType = XamlType.SilverlightStackPanel;
                    break;

                case "FileSaveAsSilverlightRichTextBox":
                    this.options.XamlType = XamlType.SilverlightRichTextBox;
                    break;

                default:
                    throw new InvalidOperationException("Invalid Control Id.");
            }

            FlowDocumentCreator creator = new FlowDocumentCreator(this.options);

            creator.Create(Globals.ThisAddIn.Application.ActiveDocument);

            this.options.XamlType = previousType;
        }

        #endregion

        #region IRibbonExtensibility Members

        /// <summary>
        /// Get the Custom UI text
        /// </summary>
        /// <param name="ribbonID">the ribbon ID</param>
        /// <returns>the Ribbon Custom UI Text</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "Stylecop: variable names should start with lowercase.")]
        public string GetCustomUI(string ribbonID)
        {
            return GetResourceText("WordFlowDocumentCreator.Ribbon1.xml");
        }

        #endregion

        #region Helpers

        /// <summary>
        /// Get resource text
        /// </summary>
        /// <param name="resourceName">the resource name</param>
        /// <returns>the resource text</returns>
        private static string GetResourceText(string resourceName)
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            string[] resourceNames = asm.GetManifestResourceNames();
            for (int i = 0; i < resourceNames.Length; ++i)
            {
                if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
                {
                    using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
                    {
                        if (resourceReader != null)
                        {
                            return resourceReader.ReadToEnd();
                        }
                    }
                }
            }

            return null;
        }

        #endregion

        #region Implementation
        /// <summary>
        /// Initialize the options from the defaults or the settings file
        /// </summary>
        private void InitializeOptions()
        {
            this.options.AutoColumnWidth = Properties.Settings.Default.AutoColumnWidth;
            this.options.AutoPagePadding = Properties.Settings.Default.AutoPagePadding;
            this.options.ColumnWidth = Properties.Settings.Default.ColumnWidth;
            this.options.ColumnWidthUnits = Properties.Settings.Default.ColumnWidthUnits;
            this.options.DropShadowNoise = Properties.Settings.Default.DropShadowNoise;
            this.options.DropShadowSoftness = Properties.Settings.Default.DropShadowSoftness;
            this.options.IsColumnWidthFlexible = Properties.Settings.Default.IsColumnWidthFlexible;
            this.options.IsHyphenationEnabled = Properties.Settings.Default.IsHyphenationEnabled;
            this.options.IsOptimalParagraphEnabled = Properties.Settings.Default.IsOptimalParagraphEnabled;
            this.options.PagePadding = Properties.Settings.Default.PagePadding;
            this.options.PagePaddingUnits = Properties.Settings.Default.PagePaddingUnits;
            this.options.XamlType = Properties.Settings.Default.XamlType;
        }

        #endregion
    }
}
